﻿#include<iostream>
#include<assert.h>
using namespace std;

// 日期类
class Date
{
public:
	int GetMonthDay(int year, int month)
	{
		// static修饰放在静态区 不用每次调用都创建
		static int monthDayArray[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
		// 判断闰年
		if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
		{
			return 29;
		}
		else
		{
			return monthDayArray[month];
		}
	}
	// 构造函数
	// 初始化列表：以一个冒号开始，接着是一个以逗号分割的数据成员列表，每个成员变量后面跟一个放在括号中的初始值或表达式
	Date(int year = 2000, int month = 1, int day = 1)
		:_year(year)
		, _month(month)
		, _day(day)
	{
		_year = year;
		_month = month;
		_day = day;
		// 检查日期的合法性
		if (!(year >= 1
			&& (month >= 1 && month <= 12)
			&& (day >= 1 && day <= GetMonthDay(year, month))))
		{
			cout << "非法日期" << _year << "-" << _month << "-" << _day << endl;
		}
	}

	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
	// 赋值运算符重载
	Date& operator=(const Date& d)
	{
		_year = d._day;
		_month = d._month;
		_day = d._day;

		// 赋值返回左操作数 以支持链式赋值
		// *this ==> d1 出了作用域还在 可以引用返回
		// 返回 d 存在的问题：权限的放大
		return *this;
	}
private:
	int _year;
	int _month;
	int _day;
};
// 栈类
class Stack
{
public:
	// 构造函数
	// 初始化列表和函数体内初始化可以混合使用
	Stack(int capacity = 4)
		: _top(0)
		, _capacity(capacity)
	{
		_a = (int*)malloc(sizeof(int) * capacity);
		if (_a == nullptr)
		{
			perror("malloc fail");
			exit(-1);
		}
		memset(_a, 0, sizeof(int) * capacity);
	}

	void push(int x)
	{
		// 扩容
		_a[_top++] = x;
	}
	// 析构函数
	~Stack()
	{
		free(_a);
		_a = nullptr;
		_top = _capacity = 0;
	}
private:
	int* _a;
	int _top;
	int _capacity;

};
class myQueue
{
public:
	// 初始化列表
	myQueue(size_t capacity = 8)
		:_popST(8)
		, _pushST(8)
		, _size(0)
	{
		// 初始化
	}
	void push(int x)
	{

	}
private:
	Stack _pushST;
	Stack _popST;
	size_t _size;
};

class B
{
public:
	// 构造函数 不是默认构造 A的成员变量初始化会报错  
	// B没有对应的默认构造函数
	//B(int b)
	//	:_b(0)
	//{

	//}
	// 默认构造
	B(int b = 0)
		:_b(0)
	{

	}
private:
	int _b;
};
// 以下类型的成员变量，必须在初始化列表初始化
// 1.const成员
// 2.引用成员
// 3.自定义类型成员（没有默构造函数）
class A
{
public:
	A()
		:_n(10) 
	{
		// _n = 10; // 报错：const成员在定义的时候必须初始化 且不能再次修改
	}
private:
	const int _n; // const成员 声明
	int _m = 1;
	B _bb;
};
class C
{
public:
	C(int a)
		:_a1(a)
		,_a2(_a1)
	{
		
	}
	void Print()
	{
		cout << _a1 << " " << _a2 << endl;
	}
private:
	// 成员变量在类中的声明次序就是其在初始化列表中的初始化顺序 与其在初始化列表中的顺序无关
	int _a2;
	int _a1;
};

void testStack()
{
	// 对象实例化是整体定义
	// 对象的每个成员定义：初始化列表
	// 每个成员都会执行初始化列表,不显式在初始化列表定义，内置类型随机值，自定义类型调默认构造函数
	// 声明时的缺省值 在初始化列表中如果该成员没有显式定义，对于内置类型就使用该缺省值
	A aa;

	Stack st1;
	Stack st2;
	Stack st3;

}
int main()
{
	//testStack();
	C cc(1);
	cc.Print();  // 1  随机值

	// 总结：
	// 尽量使用初始化列表初始化
	// 一个类尽量提供默认构造函数（全缺省的）


	return 0;
}